package com.liuugoqing.structural.proxy.cglib_proxy;


import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * cglib代理
 *
 * @Author : liugq
 * @Date : 2022/7/3 23:59
 * @See : 参考类
 * @Since： JDK1.8
 * @Version : 1.0
 */
public class CglibProxyFactory {
    /**
     * 获取代理类
     *
     * @param trainStation 需要代理的类
     * @return 代理好的类
     */
    public static TrainStation getProxyInstance(TrainStation trainStation) {
        /**
         * 动态代理：
         *  特点：字节码随用随创建，随用随加载
         *  作用：不修改源码的基础上对方法增强
         *  分类：
         *      基于接口的动态代理
         *      基于子类的动态代理
         *  基于子类的动态代理：
         *      涉及的类：Enhancer
         *      提供者：第三方cglib库
         *  如何创建代理对象：
         *      使用Enhancer类中的create方法
         *  创建代理对象的要求：
         *      被代理类不能是最终类
         *  create方法的参数：
         *      Class：字节码
         *          它是用于指定被代理对象的字节码。
         *
         *      Callback：用于提供增强的代码
         *          它是让我们写如何代理。我们一般都是些一个该接口的实现类，通常情况下都是匿名内部类，但不是必须的。
         *          此接口的实现类都是谁用谁写。
         *          我们一般写的都是该接口的子接口实现类：MethodInterceptor
         */
        return (TrainStation) Enhancer.create(trainStation.getClass(),
                /**
                 * 执行被代理对象的任何方法都会经过该方法
                 * @param proxy
                 * @param method
                 * @param args
                 *    以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
                 * @param proxy ：当前执行方法的代理对象
                 * @return
                 * @throws Throwable
                 */
                (MethodInterceptor) (obj, method, args, proxy) -> {
                    System.out.println("cglib增强");
                    return method.invoke(trainStation,args);
                });
    }


}
